﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq; 



namespace DataAccesLayer
{
    public class EmployeeDataAccesLayer 
    {
        protected static readonly string DefaultRole = "User";

        System.Data.Linq.Table<Employee> _employees;

        public System.Data.Linq.Table<Employee> Employees
        {
            get { return _employees; }
            set { _employees = value; }
        }

        public eQualDataContext DataContext
        {
            get
            {
                return (eQualDataContext)Employees.Context;
            }
        }

        public   EmployeeDataAccesLayer()
        {
            _employees = EQualDataProvider .EQualDataContext.Employees; 
        }

        public void DeleteEmployee(Employee employee)
        {
            throw new NotImplementedException();
        }

        public IEnumerable <Employee> GetEmployees()
        {
            var employees = from c in Employees 
                            select c;

            return employees.ToList();

        }

        public void UpdateEmployee(Employee  customer)
        {
            throw new NotImplementedException();
        }

        #region IEmployeeDataAccesLayer Members

        public IEnumerable <Employee> GetEmploeesDocumentNotification(string documentId)
        {
            eQualDataContext DataContext = new eQualDataContext();
            int docId=-1;
            int.TryParse (documentId ,out docId);

            if (docId > 0)
            {
                var notifidedEmployees =
                from d in DataContext.Documents
                from d_e in DataContext.Document_To_Employees
                from e in DataContext.Employees
                where d.Id == docId
                where d.Id == d_e.id_document
                where d_e.id_Employee == e.id
                select e;

                return notifidedEmployees.ToList();
            }
            return null;
        }

        public void RemoveEmployeeToBeNotified(Document document, Employee employee)
        {
            RemoveEmployeeToBeNotified(document.Id, employee.id);
        }

        public void RemoveEmployeeToBeNotified(int   documentId, int employeeId)
        {

            // find the entries in employee to document table ...
            var accosiationsToBeDeleted = //from d in provider.Documents
                                          from d_e in DataContext.Document_To_Employees
                                          //from e in provider.Employees
                                          where d_e.id_document == documentId
                                          where d_e.id_Employee == employeeId
                                          select d_e;
            object d = accosiationsToBeDeleted.ToList();

            if (accosiationsToBeDeleted.Count() == 0) throw new Exception("there are no acossiations document_to_employee");
            // and delete them 
            DataContext.Document_To_Employees.DeleteAllOnSubmit(accosiationsToBeDeleted);
            DataContext.SubmitChanges();

        }

        public void AddEmployeeToBeNotified(Document document, Employee employee)
        {
            AddEmployeeToBeNotified(document.Id, employee.id);
        }

        public void AddEmployeeToBeNotified(int  documentId,int  employeeId)
        {
            eQualDataContext DataContext = new eQualDataContext();
            try
            {
                if (DataContext.Document_To_Employees.SingleOrDefault 
                    (de => de.id_document == documentId &&
                        de.id_Employee == employeeId) != null) return;
                //create the new accosiation and and it 
                Document_To_Employee Document_Employee_accosiation = new Document_To_Employee();
                Document_Employee_accosiation.id_document = documentId;
                Document_Employee_accosiation.id_Employee = employeeId;

                DataContext.Document_To_Employees.InsertOnSubmit(Document_Employee_accosiation);
                DataContext.SubmitChanges();
            }
            catch (Exception e) { throw new Exception("Cannot add new asccosiation to document"); }
        }

        public void AddGroupToBeNotified(Document doc,Role role)
        {
            eQualDataContext DataContext = new eQualDataContext();

            var EmplyeesGroup = GetEmployeesGroup(role);

            foreach (Employee e in EmplyeesGroup)
                AddEmployeeToBeNotified(doc, e);
 
        }

        public void RemoveGroupToBeNotified(Document doc, Role role)
        {
            eQualDataContext DataContext = new eQualDataContext();

            var EmplyeesGroup = GetEmployeesGroup(role);

            foreach (Employee e in EmplyeesGroup)
                RemoveEmployeeToBeNotified (doc, e);
        }

        public void AddRoleDistribution(IList<Role> roles, Document document)
        {
            if (roles == null) return;
            foreach (Role role in roles)
                AddRoleDistribution(role,document );
        }

        public void AddRoleDistribution(Role role, Document document)
        {
            eQualDataContext DataContext = new eQualDataContext();
            try
            {
                if (IsDestributedToRole(role, document)) return;

                Document_To_Role Document_Role_accosiation = new Document_To_Role();
                Document_Role_accosiation.DocumentId = document.Id;
                Document_Role_accosiation.Role = role.Name;

                DataContext.Document_To_Roles.InsertOnSubmit(Document_Role_accosiation);
                DataContext.SubmitChanges();
            }
            catch (Exception e) { throw new Exception("Cannot add new asccosiation to document"); }
        }

        public void SetRoleDistribution(IList<Role> roles, Document document)
        {
            foreach (Role role in roles)
            {
                if (!IsDestributedToRole(role, document))
                    RemoveRoleDistribution(role, document);

                if (IsDestributedToRole(role, document))
                    continue;
                else
                    AddRoleDistribution(role, document);
            }
        }

        public void RemoveRoleDistribution(Role role, Document document)
        {
            if (!IsDestributedToRole(role, document)) return;

            eQualDataContext DataContext = new eQualDataContext();
            Document_To_Role d_r =  DataContext.Document_To_Roles.FirstOrDefault(d_t => d_t.Role == role.Name && d_t.DocumentId == document.Id);
            DataContext.Document_To_Roles.DeleteOnSubmit(d_r);
            DataContext.SubmitChanges();

        }

        private bool IsDestributedToRole(Role role, Document document)
        {
            eQualDataContext DataContext = new eQualDataContext();
            return DataContext .Document_To_Roles .FirstOrDefault (d_t=>d_t .Role ==role.Name && d_t .DocumentId ==document.Id )!=null;
        }

        private System.Collections.IEnumerable GetEmployeesGroup(Role role)
        {
            eQualDataContext DataContext = new eQualDataContext();

            return (from e in DataContext.Employees
                    where e.Role == role.Name
                    select e).ToList();
        }

        #endregion

        public Employee GetEmployeeByExample(Employee employee)
        {
            var empl = from emp in DataContext.Employees
                       where (emp.id == employee.id
                       || emp.name == employee.name
                       || emp.surname == employee.surname)
                       select emp;
            if (empl.Count ()>0) 
                if(empl.First () is Employee )
                    return empl.First () as Employee;
            return null;
        }

        public void AddNewEmployee(Employee employee)
        {
            eQualDataContext DataContext = new eQualDataContext();

            if (GetEmployeeByExample (employee)!= null) return;

            try
            {
                SetDefaultRole(employee, DataContext);

                if (!DataContext.Employees.Contains(employee))
                    DataContext.Employees.InsertOnSubmit(employee);

                DataContext.SubmitChanges();
            }
            catch (Exception e){ throw new Exception("Cannot Add Employee",e); }
        }

        protected virtual void SetDefaultRole(Employee employee, eQualDataContext DataContext)
        {
            employee.Role1 = DataContext.Roles.First(e => e.Name == DefaultRole);
        }

        public virtual void SetEmployeeRole(Employee employee , string role)
        {
            employee.Role = role;
        }

        public void DeleteEmployee(System.Collections.IList iList)
        {
            foreach (Employee empl in iList)DeleteEmployee(empl);
        }

        public void RemoveEmployeeToBeNotified(Document document, System.Collections.IList iList)
        {
            foreach (Employee empl in iList)RemoveEmployeeToBeNotified(document, empl);
        }

        public IEnumerable < DataAccesLayer.Work_Experiance> GetEmployeeExperience(Employee empl)
        {
            eQualDataContext DataContext = new eQualDataContext();
            return (from w_e in DataContext.Work_Experiances where empl.id  == w_e.EmployeeId
                     select w_e).ToList();
        }

        public void AddWorkingExperianceToEmployee(Work_Experiance  w_e,Employee empl)
        {
            return;
            w_e.EmployeeId = empl.id;
            DataContext.Work_Experiances.InsertOnSubmit(w_e);
            DataContext.SubmitChanges();
        }

        public object GetEmployeeTrainings(object ActiveItem)
        {
            eQualDataContext DataContext = new eQualDataContext();
/*
            return (from w_e in DataContext.tr
                    where empl.id == w_e.EmployeeId
                    select w_e).ToList();
      
            return null; 
 */
            return null;
        }

        public System.Collections.IEnumerable GetTrainings()
        {
            return new eQualDataContext().Trainings.ToList();
        }

        public void AddNewTraining(object p)
        {
            eQualDataContext DataContext = new eQualDataContext();
            if (DataContext.Trainings.SingleOrDefault(t => t.TrainigId == (p as Training).TrainigId) != null) return;
            DataContext.Trainings.InsertOnSubmit(p as Training);
            DataContext.SubmitChanges();
        }

        public IList<Role> GetRoles()
        {
            return new DataAccesLayer.eQualDataContext().Roles.ToList();
        }

        public System.Collections.IEnumerable GetRolesDestribution(Document document)
        {
            eQualDataContext DataContext = new eQualDataContext();

            var roles = (from d_r in DataContext.Document_To_Roles
                         from r in DataContext.Roles
                         where d_r.DocumentId == document.Id
                         where d_r.Role == r.Name
                         select r);

            return roles.ToList();
        }


        public System .Collections .IEnumerable  GetTrainingParticipants(object training)
        {
            Training _training = training as Training ;

            eQualDataContext DataContext = new eQualDataContext();

            var participants = (from ep in DataContext.Training_Participants   
                         from e in DataContext.Employees  
                         where _training . TrainigId == ep .TrainingId 
                         where  ep .EmployeeId ==e.id 
                         select e);

            return participants.ToList();
        }

        public void AddEmployeeTrainings(object training, object employee)
        {
            if (IsEmployeeInTraining(training, employee)) return;

            Training _training = training as Training;
            Employee _employee  = employee as Employee ;

            eQualDataContext DataContext = new eQualDataContext();

            Training_Participant trainingParticipation = new Training_Participant();
            trainingParticipation.EmployeeId = _employee.id;
            trainingParticipation.TrainingId = _training.TrainigId;
            DataContext.Training_Participants.InsertOnSubmit(trainingParticipation);
            DataContext.SubmitChanges();
        }

        private bool IsEmployeeInTraining(object training, object employee)
        {
            return new eQualDataContext().Training_Participants.SingleOrDefault(
               tp => tp.TrainingId  == (training as Training).TrainigId &&
               tp.EmployeeId == (employee as Employee).id) != null;
        }

        public void RemoveEmployeeTrainings(object training, System.Collections.IList employees)
        {
            foreach (Employee empl in employees)
            {
                RemoveEmployeeTrainings(training, empl);
            }
        }

        private void RemoveEmployeeTrainings(object training, Employee employee)
        {
            Training _training = training as Training;
            Employee _employee = employee as Employee;

            eQualDataContext DataContext = new eQualDataContext();

            var participants = (from ep in DataContext.Training_Participants
                                where _training.TrainigId == ep.TrainingId
                                where _employee.id == ep.EmployeeId 
                                select ep);

            DataContext.Training_Participants.DeleteAllOnSubmit  (participants);
            DataContext.SubmitChanges();
        }

        public System.Collections.IEnumerable GetProposalTypes()
        {
            return new eQualDataContext().ProposalTypes.ToList();
        }

        public System.Collections.IEnumerable GetProposalsStatusTypes()
        {
            return new eQualDataContext().ProposalStatus.ToList();
        }

        public object GetProposals()
        {
            return new eQualDataContext().Proposals.ToList ();
        }

        public void AddNewProposal(object proposal)
        {
            if (!(proposal is Proposal) || proposal == null) return;

            eQualDataContext DataContext = new eQualDataContext();

            DataContext.Proposals.InsertOnSubmit(proposal as Proposal);
            DataContext.SubmitChanges();
                

        }
    }
}
